package org.dromara.system.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.RequiredArgsConstructor;
import org.dromara.common.core.exception.ServiceException;
import org.dromara.common.core.utils.MapstructUtils;
import org.dromara.common.core.utils.StringUtils;
import org.dromara.common.mybatis.core.page.PageQuery;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.system.domain.DeviceGroup;
import org.dromara.system.domain.bo.DeviceGroupBo;
import org.dromara.system.domain.vo.DeviceGroupVo;
import org.dromara.system.mapper.DeviceGroupMapper;
import org.dromara.system.service.IDeviceGroupService;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 设备分类Service业务层处理
 *
 * @author Lion Li
 * @date 2024-10-09
 */
@RequiredArgsConstructor
@Service
public class DeviceGroupServiceImpl implements IDeviceGroupService {

    private final DeviceGroupMapper baseMapper;

    /**
     * 查询设备分类
     *
     * @param id 主键
     * @return 设备分类
     */
    @Override
    public DeviceGroupVo queryById(Long id) {
        return baseMapper.selectVoById(id);
    }

    /**
     * 分页查询设备分类列表
     *
     * @param bo        查询条件
     * @param pageQuery 分页参数
     * @return 设备分类分页列表
     */
    @Override
    public TableDataInfo<DeviceGroupVo> queryPageList(DeviceGroupBo bo, PageQuery pageQuery) {
        LambdaQueryWrapper<DeviceGroup> lqw = buildQueryWrapper(bo);
        Page<DeviceGroupVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
        return TableDataInfo.build(result);
    }

    /**
     * 查询符合条件的设备分类列表
     *
     * @param bo 查询条件
     * @return 设备分类列表
     */
    @Override
    public List<DeviceGroupVo> queryList(DeviceGroupBo bo) {
        LambdaQueryWrapper<DeviceGroup> lqw = buildQueryWrapper(bo);
        return baseMapper.selectVoList(lqw);
    }

    private LambdaQueryWrapper<DeviceGroup> buildQueryWrapper(DeviceGroupBo bo) {
        LambdaQueryWrapper<DeviceGroup> lqw = Wrappers.lambdaQuery();
        lqw.like(StringUtils.isNotBlank(bo.getGroupName()), DeviceGroup::getGroupName, bo.getGroupName());
        lqw.eq(bo.getParentId() != null, DeviceGroup::getParentId, bo.getParentId());
        lqw.eq(bo.getId() != null, DeviceGroup::getId, bo.getId());
        return lqw;
    }

    /**
     * 新增设备分类
     *
     * @param bo 设备分类
     * @return 是否新增成功
     */
    @Override
    public Boolean insertByBo(DeviceGroupBo bo) {
        DeviceGroup add = MapstructUtils.convert(bo, DeviceGroup.class);
        validEntityBeforeSave(add);
        boolean flag = baseMapper.insert(add) > 0;
        if (flag) {
            bo.setId(add.getId());
        }
        return flag;
    }

    /**
     * 修改设备分类
     *
     * @param bo 设备分类
     * @return 是否修改成功
     */
    @Override
    public Boolean updateByBo(DeviceGroupBo bo) {
        DeviceGroup update = MapstructUtils.convert(bo, DeviceGroup.class);
        validEntityBeforeSave(update);
        return baseMapper.updateById(update) > 0;
    }

    /**
     * 保存前的数据校验
     */
    private void validEntityBeforeSave(DeviceGroup entity) {
        //TODO 做一些数据校验,如唯一约束
    }

    /**
     * 校验并批量删除设备分类信息
     *
     * @param ids     待删除的主键集合
     * @param isValid 是否进行有效性校验
     * @return 是否删除成功
     */
    @Override
    public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
        if (isValid) {
            //判断ids中是否有数据含有子节点
            if (hasChildByParentId(ids)) {
                throw new ServiceException("存在子分类,不允许删除");
            }
        }
        return baseMapper.deleteByIds(ids) > 0;
    }

    /**
     * 检查给定的ids中是否有任何一个ID拥有子节点
     *
     * @param ids 要检查的ID集合
     * @return 如果存在子节点返回true，否则返回false
     */
    private boolean hasChildByParentId(Collection<Long> ids) {
        LambdaQueryWrapper<DeviceGroup> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.in(DeviceGroup::getParentId, ids);
        return baseMapper.selectCount(queryWrapper) > 0;
    }

    @Override
    public String getGroupName(Long groupId) {
        DeviceGroup group = baseMapper.selectById(groupId);
        return group == null ? "" : group.getGroupName();
    }

    @Override
    public List<DeviceGroupVo> getGroupList(DeviceGroupBo bo) {
        LambdaQueryWrapper<DeviceGroup> lqw = buildQueryWrapper(bo);
        List<DeviceGroupVo> deviceGroupVos = baseMapper.selectVoList(lqw);
        Map<Long, DeviceGroupVo> groupMap = deviceGroupVos.stream()
                .collect(Collectors.toMap(DeviceGroupVo::getId, group -> group));

        // 构建分类树
        List<DeviceGroupVo> tree = new ArrayList<>();
        for (DeviceGroupVo group : deviceGroupVos) {
            if (!groupMap.containsKey(group.getParentId())) {
                tree.add(buildTree(group, groupMap));
            }
        }
        return tree;
    }

    @Override
    public List<DeviceGroupVo> getAllGroup() {
        List<DeviceGroupVo> deviceGroupVos = baseMapper.selectVoList();
        Map<Long, DeviceGroupVo> groupMap = deviceGroupVos.stream()
                .collect(Collectors.toMap(DeviceGroupVo::getId, group -> group));

        // 构建分类树
        List<DeviceGroupVo> tree = new ArrayList<>();
        for (DeviceGroupVo group : deviceGroupVos) {
            if (!groupMap.containsKey(group.getParentId())) {
                tree.add(buildTree(group, groupMap));
            }
        }
        return tree;
    }

    @Override
    public Long getRootNodeId(Long nodeId) {
        return findRootNode(nodeId);
    }

    private Long findRootNode(Long currentNodeId) {
        DeviceGroup deviceGroup = baseMapper.selectById(currentNodeId);
        if (deviceGroup == null) {
            throw new IllegalArgumentException("Node with ID " + currentNodeId + " does not exist.");
        }
        if (deviceGroup.getParentId() == 0) {
            return deviceGroup.getId();
        } else {
            return findRootNode(deviceGroup.getParentId());
        }
    }


    /**
     * 递归构建分类树
     *
     * @param group    当前分类
     * @param groupMap 所有分类的Map
     * @return 构建好的分类树
     */
    private DeviceGroupVo buildTree(DeviceGroupVo group, Map<Long, DeviceGroupVo> groupMap) {
        List<DeviceGroupVo> children = groupMap.values().stream()
                .filter(child -> child.getParentId().equals(group.getId()))
                .map(child -> buildTree(child, groupMap))
                .collect(Collectors.toList());

        group.setChildren(children);
        return group;
    }
}
